home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 4
/
Aminet 4 - November 1994.iso
/
aminet
/
comm
/
net
/
dnet2_10_13.lha
/
DNet
/
Amiga
/
Sourcen.lha
/
doshand
/
uuser.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-14
|
13KB
|
533 lines
/*
* UUSER.C UUSER:devicename/unitnumber/options
* UUSER:serial.device/0/R1000
*
* options:
* Rn Set read timeout when no data available to n millisecs
* C0 Ignore carrier detect
*
* features:
* 1K asynchronous write capability (write 0 bytes to sync up)
* programmable read-timeout (Getty starts procs up w/ 1sec to)
*
* combined together, you can easily implement 100% efficient
* protocols even with that 1 second read timeout!
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <devices/serial.h>
#include <devices/timer.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
#include <hardware/cia.h>
#include <proto/all.h>
#define WRITEBUFSIZE 1024
#define MPC (MEMF_PUBLIC|MEMF_CLEAR) /* options to AllocMem() */
#define BTOC(x, type) ((type *)((long)x << 2))
#define CTOB(x) ((BPTR)((long)x >> 2))
#define DOS_FALSE 0
#define DOS_TRUE -1
typedef struct IOExtSer IOS;
typedef struct timerequest IOT;
typedef struct IORequest IOR;
typedef struct timeval TimeVal;
typedef struct FileLock LOCK;
typedef struct DosPacket Packet;
typedef struct Process PROC;
typedef struct DeviceNode DEVNODE;
typedef struct FileHandle FH;
typedef struct Message MSG;
typedef struct Node NODE;
typedef struct List LIST;
typedef struct MsgPort PORT;
typedef struct SHandle {
NODE Node;
IOT Iot; /* wait-for-char and read req */
IOS Ios;
IOS Iosr; /* 1005 */
IOS Iosw; /* 1005,1006 */
char IotIP;
char IosrIP;
char IoswIP;
char RxIn[1]; /* one char buffer */
char *TxOut; /* asynch write buffer */
Packet *RPacket; /* current pending read packet */
Packet *WPacket; /* current pending write packet */
short Flags;
LIST RxWait; /* requests waiting for data */
LIST TxWait; /* requests waiting to write */
LIST CxWait; /* wait for char */
TimeVal ReadTo;
} SHandle;
#define HF_IGNORECD 0x01
#define HF_CDLOST 0x02
#define HF_RTO 0x04
#define HF_DONTLOCK 0x08 /* if G option for from-getty */
extern Packet *taskwait(); /* wait for a message */
long SysBase; /* required to make Exec calls */
char ScrBuf[256]; /* Scratch buffer */
PORT *IoSink;
LIST HanList;
LIST NodList;
IOT Iot; /* Iot master, also used for CD */
char IotIP;
void AttemptRead();
void AttemptWrite();
void AbortPackets();
void StartTimer();
__saveds void
_dummy()
{
PROC *myproc;
DEVNODE *mynode;
UBYTE notdone;
long mask;
SysBase = *(long *)4;
IoSink = CreatePort(NULL, 0);
NewList(&HanList);
NewList(&NodList);
Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0);
Iot.tr_node.io_Command = TR_ADDREQUEST;
Iot.tr_time.tv_secs = 4;
Iot.tr_time.tv_micro= 0;
SendIO(&Iot);
IotIP = 1;
myproc = (PROC *)FindTask(0L);
/*
* INITIAL STARTUP MESSAGE
*/
{
Packet *mypkt;
mypkt = taskwait(myproc);
mynode = BTOC(mypkt->dp_Arg3, DEVNODE);
mynode->dn_Task = &myproc->pr_MsgPort;
returnpkt(mypkt, myproc, DOS_TRUE, 0);
}
loop:
notdone = 1;
mask = (1 << IoSink->mp_SigBit) | (1 << myproc->pr_MsgPort.mp_SigBit);
while (notdone) {
Packet *mypkt; /* dos packet received */
IOR *ior;
SHandle *handle;
long type; /* type of packet */
ior = (IOR *)GetMsg(IoSink);
mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
if (mypkt)
mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
while (mypkt == NULL && ior == NULL) {
Wait(mask);
ior = (IOR *)GetMsg(IoSink);
mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
if (mypkt)
mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
}
/*
* Make sure there is at least one free node in node list
*/
if (NodList.lh_Head == (NODE *)&NodList.lh_Tail) {
NODE *pknode = AllocMem(sizeof(NODE), MPC);
AddTail(&NodList, pknode);
}
/*
* Returned IO request, sift through lists to find it.
*/
if (ior) {
if (ior == &Iot) { /* Check for carrier lost */
for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
if (!(handle->Flags & HF_IGNORECD) && !(handle->Flags & HF_CDLOST)) {
handle->Ios.IOSer.io_Command = SDCMD_QUERY;
DoIO(&handle->Ios);
if (handle->Ios.io_Status & CIAF_COMCD) {
handle->Flags |= HF_CDLOST;
AbortPackets(handle, myproc);
}
}
}
if (HanList.lh_Head == (NODE *)&HanList.lh_Tail) {
IotIP = 0;
} else {
Iot.tr_time.tv_secs = 4;
Iot.tr_time.tv_micro= 0;
SendIO(&Iot);
IotIP = 1;
}
} else
for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
if (ior == (IOR *)&handle->Iosr) {
returnpkt(handle->RPacket, myproc, handle->Iosr.IOSer.io_Actual, 0);
handle->IosrIP = 0;
handle->RPacket = NULL;
if (handle->IotIP) {
AbortIO(&handle->Iot);
WaitIO(&handle->Iot);
handle->IotIP = 0;
}
AttemptRead(handle, myproc);
}
if (ior == (IOR *)&handle->Iosw) {
handle->IoswIP = 0;
if (handle->WPacket) {
handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
handle->Iosw.IOSer.io_Length= handle->WPacket->dp_Arg3 - handle->WPacket->dp_Res1;
SendIO(&handle->Iosw);
handle->IoswIP = 1;
handle->WPacket->dp_Res1 = handle->WPacket->dp_Arg3;
returnpktplain(handle->WPacket, myproc);
handle->WPacket = NULL;
} else {
AttemptWrite(handle, myproc);
}
}
if (ior == (IOR *)&handle->Iot) {
handle->IotIP = 0;
if ((handle->Flags & HF_RTO) && handle->IosrIP) {
AbortIO(&handle->Iosr);
}
}
}
}
if (mypkt) {
mypkt->dp_Res1 = DOS_TRUE; /* default return value */
mypkt->dp_Res2 = 0; /* default no error */
type = mypkt->dp_Type; /* packet type */
/*
* Extract pipe pointer (only applies to read/write)
*/
handle = (SHandle *)mypkt->dp_Arg1; /* READ/WRITE only */
switch(type) {
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT:
case ACTION_FINDUPDATE:
if (IotIP == 0)
StartTimer(4);
{
FH *fh = BTOC(mypkt->dp_Arg1, FH);
char *path = BTOC(mypkt->dp_Arg3, char);
char *unit;
long n;
movmem(path + 1, ScrBuf, *path);
ScrBuf[*path] = 0;
path = ScrBuf;
handle = AllocMem(sizeof(SHandle), MPC);
if (strcmp(ScrBuf, "*") == 0)
strcpy(ScrBuf, "serial.device/0");
for (unit = path; *unit && *unit != '/'; ++unit) {
if (*unit == ':')
path = unit + 1;
}
if (*unit == '/') {
char *opts;
*unit = 0;
++unit;
for (opts = unit; *opts && *opts != '/'; ++opts);
while (*opts) {
n = atoi(opts + 1);
switch(*opts) {
case '/':
break;
case 'R':
handle->ReadTo.tv_secs = n / 1000;
handle->ReadTo.tv_micro= (n % 1000) * 1000;
handle->Flags |= HF_RTO;
break;
case 'C':
handle->Flags |= HF_IGNORECD;
break;
case 'G':
if (n)
handle->Flags |= HF_DONTLOCK;
break;
}
++opts;
}
}
/* proc = (PROC *)mypkt->dp_Port->mp_SigTask; */
/*
* Open the device
*/
handle->Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
handle->Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
if (OpenDevice(path, atoi(unit), &handle->Ios, 0)) {
FreeMem(handle, sizeof(SHandle));
mypkt->dp_Res1 = DOS_FALSE;
mypkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
returnpktplain(mypkt, myproc);
break;
}
fh->fh_Arg1 = (long)handle;
fh->fh_Port = (struct MsgPort *)DOS_TRUE;
handle->Iosr = handle->Ios;
handle->Iosw = handle->Ios;
handle->Iosr.IOSer.io_Command = CMD_READ;
handle->Iosw.IOSer.io_Command = CMD_WRITE;
handle->Iot = Iot;
NewList(&handle->RxWait);
NewList(&handle->TxWait);
NewList(&handle->CxWait);
AddTail(&HanList, handle);
returnpktplain(mypkt, myproc);
}
break;
case ACTION_END:
Remove(handle);
if (handle->IosrIP) {
AbortIO(&handle->Iosr);
WaitIO(&handle->Iosr);
}
if (handle->IoswIP) {
WaitIO(&handle->Iosw);
}
if (handle->IotIP) {
AbortIO(&handle->Iot);
WaitIO(&handle->Iot);
}
AbortPackets(handle, myproc);
CloseDevice(&handle->Ios);
returnpktplain(mypkt, myproc);
if (handle->TxOut)
FreeMem(handle->TxOut, WRITEBUFSIZE);
FreeMem(handle, sizeof(SHandle));
break;
case ACTION_READ:
{
NODE *pknode = RemHead(&NodList);
mypkt->dp_Res1 = 0;
pknode->ln_Name = (char *)mypkt;
AddTail(&handle->RxWait, pknode);
AttemptRead(handle, myproc);
}
break;
case ACTION_WRITE:
{
NODE *pknode = RemHead(&NodList);
mypkt->dp_Res1 = 0;
pknode->ln_Name = (char *)mypkt;
AddTail(&handle->TxWait, pknode);
AttemptWrite(handle, myproc);
}
break;
case ACTION_WAIT_CHAR:
default:
returnpkt(mypkt, myproc, DOS_FALSE, ERROR_ACTION_NOT_KNOWN);
break;
}
}
}
/*
* Can only exit if no messages pending. There might be a window
* here, but there is nothing that can be done about it.
*/
Forbid();
if (taskpktrdy(myproc)) {
Permit();
goto loop;
}
mynode->dn_Task = FALSE;
Permit();
if (IotIP) {
AbortIO(&Iot);
WaitIO(&Iot);
}
CloseDevice(&Iot);
/* we are a process "so we fall off the end of the world" */
/* MUST fall through */
}
void
AttemptRead(handle, myproc)
SHandle *handle;
PROC *myproc;
{
Packet *mypkt;
NODE *pknode;
if (handle->Flags & HF_CDLOST) {
AbortPackets(handle, myproc);
return;
}
loop:
if (handle->IosrIP == 0 && (pknode = RemHead(&handle->RxWait))) {
long n;
AddTail(&NodList, pknode);
mypkt = (Packet *)pknode->ln_Name;
/*
* special case. If you read 0 bytes, 0 is returned if data
* is pending, else -1, and NO timeout occurs.
*/
handle->Ios.IOSer.io_Command = SDCMD_QUERY;
DoIO(&handle->Ios);
if (mypkt->dp_Arg3 == 0) {
if (handle->Ios.IOSer.io_Actual > 0)
returnpkt(mypkt, myproc, 0, 0); /* 0=data rdy */
else
returnpkt(mypkt, myproc, -1, 0); /* -1=data not rdy */
goto loop;
}
if ((n = handle->Ios.IOSer.io_Actual) > 0) {
if (n > mypkt->dp_Arg3)
n = mypkt->dp_Arg3;
handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
handle->Iosr.IOSer.io_Length = n;
DoIO(&handle->Iosr);
mypkt->dp_Res1 = handle->Iosr.IOSer.io_Actual;
returnpktplain(mypkt, myproc);
goto loop;
}
handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
handle->Iosr.IOSer.io_Length = 1;
SendIO(&handle->Iosr);
handle->IosrIP = 1;
handle->RPacket = mypkt;
if (handle->Flags & HF_RTO) {
if (handle->IotIP) {
AbortIO(&handle->Iot);
WaitIO(&handle->Iot);
}
handle->Iot.tr_time = handle->ReadTo;
SendIO(&handle->Iot);
handle->IotIP = 1;
}
}
}
void
AttemptWrite(handle, myproc)
SHandle *handle;
PROC *myproc;
{
Packet *mypkt;
NODE *pknode;
if (handle->Flags & HF_CDLOST) {
AbortPackets(handle, myproc);
return;
}
if (handle->IoswIP == 0 && (pknode = RemHead(&handle->TxWait))) {
AddTail(&NodList, pknode);
mypkt = (Packet *)pknode->ln_Name;
if (handle->TxOut == NULL)
handle->TxOut = AllocMem(WRITEBUFSIZE, MPC);
if (mypkt->dp_Arg3 <= WRITEBUFSIZE) { /* fully asynch */
movmem((char *)mypkt->dp_Arg2, handle->TxOut, mypkt->dp_Arg3);
handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
handle->Iosw.IOSer.io_Length = mypkt->dp_Arg3;
SendIO(&handle->Iosw);
mypkt->dp_Res1 = mypkt->dp_Arg3;
returnpktplain(mypkt, myproc);
handle->WPacket = NULL;
} else { /* semi-asynch */
long n = mypkt->dp_Arg3 - WRITEBUFSIZE;
handle->Iosw.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
handle->Iosw.IOSer.io_Length = n;
SendIO(&handle->Iosw);
movmem((char *)mypkt->dp_Arg2 + n, handle->TxOut, WRITEBUFSIZE);
mypkt->dp_Res1 += n;
handle->WPacket = mypkt;
}
handle->IoswIP = 1;
}
}
void
AbortPackets(handle, myproc)
SHandle *handle;
{
NODE *pknode;
Packet *mypkt;
if (handle->RPacket)
returnpktplain(handle->RPacket, myproc);
if (handle->WPacket)
returnpktplain(handle->RPacket, myproc);
handle->RPacket = NULL;
handle->WPacket = NULL;
while (pknode = RemHead(&handle->RxWait)) {
mypkt = (Packet *)pknode->ln_Name;
if (mypkt->dp_Arg3 == 0)
mypkt->dp_Res1 = 0; /* for poll, return data rdy */
else
mypkt->dp_Res1 = -1;
returnpktplain(mypkt, myproc);
AddTail(&NodList, pknode);
}
while (pknode = RemHead(&handle->TxWait)) {
mypkt = (Packet *)pknode->ln_Name;
mypkt->dp_Res1 = -1;
returnpktplain(mypkt, myproc);
AddTail(&NodList, pknode);
}
}
void
StartTimer(secs)
{
if (IotIP) {
AbortIO(&Iot);
WaitIO(&Iot);
}
Iot.tr_time.tv_secs = secs;
Iot.tr_time.tv_micro= 0;
SendIO(&Iot);
IotIP = 1;
}